<?php

class App_Model extends Model {
    var $_model_name = NULL;
    var $_table_name = NULL;
	
    function App_Model() {
        parent::Model();
		date_default_timezone_set('Asia/Jakarta');
    }

	// return an array of accessible resources
	function get_model_authorization(){
		// not implemented yet
	}
	
    public function set_model_name($model_name = NULL) {
        $this->_model_name = $model_name;
    }
	
    public function get_model_name() {
        return ($this->_model_name);
    }
	
    public function set_table_name($table_name = NULL) {
        $this->_table_name = $this->config->item('table_prefix') . $table_name;
    }
	
    public function get_table_name() {
        return ($this->_table_name);
    }

	public function call_procedure($procedure_name = NULL, $arguments = array()){
		$sql = '';
		$sql .= 'CALL ';
		$sql .= ($this->config->item('procedure_prefix') . $procedure_name);
		$escaped_arguments = array();
		$question_marks = array();
		foreach($arguments as $argument){
			if(is_string($argument)){
				$escaped_arguments[] = $this->db->escape($argument);
			}else{
				$escaped_arguments[] = $argument;
			}
			$question_marks[] = '?';
		}
		$sql .= ('(' . implode(', ', $question_marks) . ')');
		
		return($this->db->query($sql, $escaped_arguments));
	}
	
    /*
	* this method is incredibly simple!
	* any retrieval may be done just by invoking this method.
	* the first argument defines selected fields.
	* the second argument defines the search criterias.
	* the third and fourth for limiting records.
	* for example, if we have a table called my_table('id', 'name', 'accepted_date', 'address', 'phone') and assume if there are about a hundred record persisted
	* then if we want to retrieve all records ['id' and 'name'] and has 'name' = 'uriel' and 'accepted_date' = '06/07/2010' 
	* start from record number 21 and return 30 first met record then we write:
	* my_table->get(
	*	array(	// set the retrieval field
	*		'id',
	*		'name',
	*	),
	*	array(	// set the search criterias
	*		'name'			=> 'uriel',
	*		'accepted_date'	=> '06/07/2010',
	*	),
	*	30,	// number of return retrieval
	*	20	// start from the record after 20, in otherwords, the record number 21
	* );
	*/
	function get($fields = NULL, $criterias = array(), $offset = 0, $limit = 0){
		$sql = 'SELECT ';
		if($fields == NULL){
			$sql .= '*';
		}else if(is_array($fields)){
			$sql .= implode(', ', $fields);
		}
		$sql .= ' FROM ' . $this->_table_name;

		if(is_array($criterias)){
			$arr_criteria = array();
			$keys = array_keys($criterias);
			foreach($keys as $key){
				if(is_array($criterias[$key])){
					$arr_criteria [] = ($key . ' IN(' . implode(', ', $criterias[$key]) . ')');
				}else{
					if($criterias[$key] == NULL){
						$arr_criteria [] = ($key . ' IS NULL');
					}else{
						$arr_criteria [] = ($key . '=\'' . $criterias[$key] . '\'');
					}
				}
			}
			$sql .= ' WHERE ' . implode(' AND ', $arr_criteria);
		}
		
		if($limit > 0){
			$sql .= (' LIMIT ' . $offset . ', ' . $limit);
		}
		
		return ($this->db->query($sql));
	}

	//ADD
	function add_record($record = NULL){
		if($record != NULL){
			$this->db->insert($this->_table_name, $record);
		}
	}

	// UPDATE
	// the criteria may consists of more than one, in an array
	// the criteria
	function update_record($record = NULL, $criterias = NULL){
		if($record != NULL && is_array($record)){
			$keys = array_keys($criterias);
			foreach($keys as $key){
				$this->db->where($key, $criterias[$key]);
			}
			$this->db->update($this->_table_name, $record);
		}
	}
	
	// updates several fields, not the record entirely
	function update_record_field($values = NULL, $criterias = NULL){
		if($values == NULL && $criterias == NULL){ // invalid arguments
			return FALSE;
		}
		$sql = 'UPDATE ' . $this->get_table_name() . ' SET ';
		if(is_array($values)){
			$arr_value = array();
			$keys = array_keys($values);
			foreach($keys as $key){
				$arr_value[] = $key . '=\'' . $values[$key] . '\'';
			}
			$sql .= implode(', ', $arr_value);
		}else{
			return FALSE;
		}
		
		if(is_array($criterias)){
			$arr_criteria = array();
			$keys = array_keys($criterias);
			foreach($keys as $key){
				$arr_criteria [] = ($key . '=\'' . $criterias[$key] . '\'');
			}
			$sql .= ' WHERE ' . implode(' AND ', $arr_criteria);
		}
//		echo($sql);
		return ($this->db->query($sql));
	}

	// DELETE
	// the criteria may consists of more than one, in an array
	// the criteria 
	function delete_record($criterias = NULL){
		$sql = 'DELETE FROM ' . $this->get_table_name();
//		print_r($criterias);
		
		if(is_array($criterias)){
			$arr_criteria = array();
			$keys = array_keys($criterias);
			foreach($keys as $key){
				if(!is_array($criterias[$key])){
					$arr_criteria [] = ($key . '=\'' . $criterias[$key] . '\'');
				}else{
					$arr_criteria [] = ($key . ' IN('. implode(', ', $criterias[$key]) .')');
				}
			}
			$sql .= ' WHERE ' . implode(' AND ', $arr_criteria);
		}
//		echo($sql);
		return ($this->db->query($sql));
	}

	function get_with_joins($joins = NULL){
		// joins is an array contains couple of joins fields
		// example:
		// array(
		//  0 => a,
		// );
	}
}

?>
